""" Loading functions for tilesets. """

import os
import pygame
from .. import debug, resource
from ..error import FormatError
from ..misc import strbool
from ..tile import TileSet,SubSurfaceTileSet,Tile
from .util import get_elem_value
import image
from xml.etree import ElementTree as ET

__all__ = (
    'load'
)

VERSION = '0.02'

def load(fileOrPath,relPath=''):
    """ Loads a tileset from a file or path.
        
        If you pass a file object rather than a file path you can use the
        `relPath` argument to specify what path filenames inside the file
        should be relative to. (Note that relPath is not used if fileOrPath
        is a string.)
        
        Returns a sbak.tile.TileSet object or an object of one of its
        subclasses, such as SubSurfaceTileSet.
        
        If any errors were found in the file data a sbak.error.FormatError is
        raised describing what went wrong.
        
        TODO: Add support for other types of sprites for tiles besides 'surface'
              and 'image' to be loaded directly from files.
                                                                 -TMG 2008-08-16
    """
    # Use relPath if needed, ignore it if not
    try:
        relPath,tail = os.path.split(fileOrPath)
    except (AttributeError,TypeError):
        pass
    
    # Start parsing
    tree = ET.parse(fileOrPath)
    root = tree.getroot()
    
    # Verify the version
    vers = root.get('version').strip()
    if vers != VERSION:
        raise FormatError("Bad version number '%s'"%vers)
    # Get type
    tsType = root.get('type','normal').lower().strip()
    
    # For normal tilesets,
    if tsType == 'normal':
        tset = TileSet()
    # For subsurface tilesets,
    elif tsType == 'subsurf':
        # Get the surface info
        
        tsSurfElem = root.find('surface')
        # Fail if the surface element isn't present
        if tsSurfElem is None:
            raise FormatError("File '%s' describes SubSurfaceTileSet with no surface."%fileOrPath)
        # Try to load the surface as a resource
        tsSurfID = tsSurfElem.get('ref',None)
        if tsSurfID:
            tsSurf = resource.depend(tsSurfID,'surface')
        # Try to load the surface as a file
        else:
            tsSurfSrc = tsSurfElem.get('src',None)
            # If there is no src, fail.
            if not tsSurfSrc:
                raise FormatError("File '%s' has surface with neither a ref nor a src."%fileOrPath)
            # Continue parsing
            tsSurfConvert = tsSurfElem.get('convert','False')
            tsSurfAlpha = tsSurfElem('alpha','False')
            # Get a surface from available data.
            tsSurf = image.load_surface(tsSurfSrc,tsSurfConvert,tsSurfAlpha)
            
        # Get the cutting info
        
        tsCutElem = root.find('cutting')
        tsCutX = get_elem_value(tsCutElem.find('x'), int, 0)
        tsCutY = get_elem_value(tsCutElem.find('y'), int, 0)
        tsCutW = get_elem_value(tsCutElem.find('w'), int, 0)
        if not tsCutW:
            raise FormatError("Missing or bad cutting 'w' element in file '%s'"%FileOrPath)
        tsCutH = get_elem_value(tsCutElem.find('h'), int, 0)
        if not tsCutH:
            raise FormatError("Missing or bad cutting 'h' element in file '%s'"%FileOrPath)
        tsCutXSep = get_elem_value(tsCutElem.find('xsep'), int, 0)
        tsCutYSep = get_elem_value(tsCutElem.find('ysep'), int, 0)
        
        # Create the tileset object
        tset = SubSurfaceTileSet(tsSurf,(tsCutX,tsCutY,tsCutW,tsCutH),
                                 (tsCutXSep,tsCutYSep))
    
    # Unknown types
    else:
        raise FormatError("Bad type '%s'"%tsType)
    
    # Parse the tileset
    tsTilesElem = root.find('tiles')
    if tsTilesElem is None: tsTilesElem = []
    for tElem in tsTilesElem:
        # Get the tile attributes
        tAttrs = (tElem.find('tileattrs') or ET.Element('tileattrs')).attrib
        # Get the groups
        tGroupsElem = tElem.find('groups')
        if tGroupsElem is not None:
            tGroups = tGroupsElem.text.split(',')
        else:
            tGroups = []
        # Get sprite information
        tSpriteElem = tElem.find('sprite')
        if tSpriteElem is not None:
            # Check for a num
            tSprNum = int(tSpriteElem.get('num','-1'))
            # If there is a num and this is a subsurf tileset,
            if tSprNum >= 0 and tsType=='subsurf':
                tset.create_tile_n(tSprNum,tGroups,tAttrs)
            # Try ref
            else:
                tSprRef = tSpriteElem.get('ref',None)
                if tSprRef:
                    tset.create_tile(resource.get(tSprRef),tGroups,tAttrs)
                # Try src
                else:
                    tSprSrc = tSpriteElem.get('src',None)
                    if tSprSrc:
                        # Join name of file head to src path
                        tSprSrc = os.path.join(relPath,tSprSrc)
                        # Load the file as an image
                        tImage = image.load_image(tSprSrc,
                            tSpriteElem.get('convert',False),
                            tSpriteElem.get('alpha',False))
                        # Create the tile
                        tset.create_tile(tImage,tGroups,tAttrs)
                    # If all else fails, create a tile with no sprite
                    else:
                        tset.create_tile(None,tGroups,tAttrs)
        # If none of the worked, create a tile with no sprite
        else:
            tset.create_tile(None,*tGroups,**tAttrs)
    
    return tset

def _autoload(agent):
    """ Internal function.
        Autoloader for tilesets.
    """
    return load(agent.src)
    
